package com.jinwei.qunguanjia.web.system.controller;

import com.jinwei.qunguanjia.common.annotation.Log;
import com.jinwei.qunguanjia.common.constant.UserConstants;
import com.jinwei.qunguanjia.common.core.domain.Response;
import com.jinwei.qunguanjia.common.enums.BusinessTypeEnum;
import com.jinwei.qunguanjia.common.utils.JsonUtils;
import com.jinwei.qunguanjia.common.utils.StringUtils;
import com.jinwei.qunguanjia.system.dto.SysDeptDTO;
import com.jinwei.qunguanjia.system.service.SysDeptService;
import com.jinwei.qunguanjia.web.system.vo.DeptRoleTreeSelectVO;
import com.jinwei.qunguanjia.web.system.vo.DeptTreeSelectVO;
import com.jinwei.qunguanjia.web.system.vo.SysDeptVO;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 部门信息
 * 
 * @author ruoyi
 */
@RestController
@RequestMapping("/system/dept")
public class SysDeptController {

    @Resource
    private SysDeptService sysDeptService;

    /**
     * 新增部门
     * @param sysDeptVO 对象
     */
    @PreAuthorize("@ss.hasPermission('system:dept:save')")
    @Log(title = "部门管理", businessType = BusinessTypeEnum.INSERT)
    @PostMapping("/save")
    public Response save(@Validated @RequestBody SysDeptVO sysDeptVO) throws IllegalAccessException {
        SysDeptDTO sysDeptDTO = new SysDeptDTO();
        BeanUtils.copyProperties(sysDeptVO, sysDeptDTO);
        if (UserConstants.NOT_UNIQUE.equals(sysDeptService.checkDeptNameUnique(sysDeptDTO))) {
            return Response.fail("新增部门" + sysDeptVO.getDeptName() + "失败，部门名称已存在");
        }
        sysDeptService.save(sysDeptDTO);
        return Response.success();
    }

    /**
     * 修改部门
     * @param sysDeptVO 对象
     */
    @PreAuthorize("@ss.hasPermission('system:dept:update')")
    @Log(title = "部门管理", businessType = BusinessTypeEnum.UPDATE)
    @PutMapping("/update")
    public Response update(@Validated @RequestBody SysDeptVO sysDeptVO) throws IllegalAccessException {
        String deptId = sysDeptVO.getDeptId();
        sysDeptService.checkDeptDataScope(deptId);
        SysDeptDTO sysDeptDTO = new SysDeptDTO();
        BeanUtils.copyProperties(sysDeptVO, sysDeptDTO);
        if (UserConstants.NOT_UNIQUE.equals(sysDeptService.checkDeptNameUnique(sysDeptDTO))) {
            return Response.fail("修改部门'" + sysDeptVO.getDeptName() + "'失败，部门名称已存在");
        } else if (sysDeptVO.getParentId().equals(deptId)) {
            return Response.fail("修改部门'" + sysDeptVO.getDeptName() + "'失败，上级部门不能是自己");
        } else if (StringUtils.equals(UserConstants.DEPT_DISABLE, sysDeptVO.getDeptStatus()) && sysDeptService.countNormalChildrenDeptById(deptId) > 0) {
            return Response.fail("该部门包含未停用的子部门！");
        }
        sysDeptService.update(sysDeptDTO);
        return Response.success();
    }

    /**
     * 删除部门
     * @param deptId 部门id
     */
    @PreAuthorize("@ss.hasPermission('system:dept:remove')")
    @Log(title = "部门管理", businessType = BusinessTypeEnum.DELETE)
    @DeleteMapping("/{deptId}")
    public Response remove(@PathVariable String deptId) throws IllegalAccessException {
        if (sysDeptService.hasChildByDeptId(deptId)) {
            return Response.fail("存在下级部门,不允许删除");
        }
        if (sysDeptService.checkDeptExistUser(deptId))
        {
            return Response.fail("部门存在用户,不允许删除");
        }
        sysDeptService.checkDeptDataScope(deptId);
        sysDeptService.remove(deptId);
        return Response.success();
    }

    /**
     * 获取部门列表
     */
    @PreAuthorize("@ss.hasPermission('system:dept:list')")
    @GetMapping("/list")
    public Response<List<SysDeptVO>> list(SysDeptVO sysDeptVO) {
        SysDeptDTO sysDeptDTO = new SysDeptDTO();
        BeanUtils.copyProperties(sysDeptVO, sysDeptDTO);
        return Response.success(JsonUtils.copyList(sysDeptService.list(sysDeptDTO), SysDeptVO.class));
    }

    /**
     * 查询部门列表（排除节点）
     */
    @PreAuthorize("@ss.hasPermission('system:dept:list')")
    @GetMapping("/list/exclude/{deptId}")
    public Response<List<SysDeptDTO>> excludeChild(@PathVariable(value = "deptId", required = false) String deptId) {
        List<SysDeptDTO> deptList = sysDeptService.list(new SysDeptDTO());
        deptList.removeIf(d -> d.getDeptId().equals(deptId) || ArrayUtils.contains(StringUtils.split(d.getAncestors(), ","), deptId + ""));
        return Response.success(deptList);
    }

    /**
     * 根据部门编号获取详细信息
     */
    @PreAuthorize("@ss.hasPermission('system:dept:query')")
    @GetMapping(value = "/{deptId}")
    public Response<SysDeptVO> getInfo(@PathVariable String deptId) throws IllegalAccessException {
        sysDeptService.checkDeptDataScope(deptId);
        return Response.success(JsonUtils.parseObject(sysDeptService.get(deptId), SysDeptVO.class));
    }

    /**
     * 获取部门下拉树列表
     */
    @GetMapping("/treeSelect")
    public Response<List<DeptTreeSelectVO>> treeSelect(SysDeptVO sysDeptVO) {
        SysDeptDTO sysDeptDTO = new SysDeptDTO();
        BeanUtils.copyProperties(sysDeptVO, sysDeptDTO);
        List<SysDeptDTO> deptList = sysDeptService.list(sysDeptDTO);
        return Response.success(buildDeptTreeSelect(deptList));
    }

    /**
     * 加载对应角色部门列表树
     */
    @GetMapping(value = "/roleDeptTreeSelect/{roleId}")
    public Response<DeptRoleTreeSelectVO> roleDeptTreeSelect(@PathVariable("roleId") String roleId) {
        List<SysDeptDTO> deptList = sysDeptService.list(new SysDeptDTO());
        DeptRoleTreeSelectVO deptRoleTreeSelectVO = new DeptRoleTreeSelectVO();
        deptRoleTreeSelectVO.setCheckedKeys(sysDeptService.listDeptByRoleId(roleId));
        deptRoleTreeSelectVO.setDeptList(buildDeptTreeSelect(deptList));
        return Response.success(deptRoleTreeSelectVO);
    }

    /**
     * 构建前端所需要下拉树结构
     *
     * @param deptList 部门列表
     * @return 下拉树结构列表
     */
    private List<DeptTreeSelectVO> buildDeptTreeSelect(List<SysDeptDTO> deptList)
    {
        List<SysDeptVO> deptTrees = JsonUtils.copyList(buildDeptTree(deptList), SysDeptVO.class);
        return deptTrees.stream().map(DeptTreeSelectVO::new).collect(Collectors.toList());
    }

    private List<SysDeptDTO> buildDeptTree(List<SysDeptDTO> deptList)
    {
        List<SysDeptDTO> returnList = new ArrayList<>();
        List<String> tempList = new ArrayList<>();
        for (SysDeptDTO dept : deptList)
        {
            tempList.add(dept.getDeptId());
        }
        for (SysDeptDTO dept : deptList)
        {
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(dept.getParentId()))
            {
                recursionFn(deptList, dept);
                returnList.add(dept);
            }
        }
        if (returnList.isEmpty())
        {
            returnList = deptList;
        }
        return returnList;
    }

    /**
     * 递归列表
     */
    private void recursionFn(List<SysDeptDTO> list, SysDeptDTO t)
    {
        // 得到子节点列表
        List<SysDeptDTO> childList = getChildList(list, t);
        t.setChildren(childList);
        for (SysDeptDTO tChild : childList)
        {
            if (hasChild(list, tChild))
            {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<SysDeptDTO> getChildList(List<SysDeptDTO> list, SysDeptDTO t)
    {
        List<SysDeptDTO> listNew = new ArrayList<>();
        for (SysDeptDTO n : list) {
            if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().equals(t.getDeptId())) {
                listNew.add(n);
            }
        }
        return listNew;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<SysDeptDTO> list, SysDeptDTO t)
    {
        return getChildList(list, t).size() > 0;
    }
}
